// Dedicated to the public domain by Christopher Diggins
// http://www.cdiggins.com

#ifndef YARD_SHARED_GRAMMAR_HPP
#define YARD_SHARED_GRAMMAR_HPP

#include "yard_text_grammar.hpp"

namespace shared_grammar
{
    using namespace yard;
    using namespace text_grammar;

    struct SymChar :
        CharSetParser<CharSet<'~','!','@','#','$','%','^','&','*','-','+','|','\\','<','>','/','?','.','='> > { };

    struct NewLine : 
        Or<CharSeq<'\r', '\n'>, CharSeq<'\n'> > { };

    struct LineComment : 
        Seq<CharSeq<'/', '/'>, UntilPast<NewLine> > { };
    
    struct FullComment : 
        Seq<CharSeq<'/', '*'>, UntilPast<CharSeq<'*', '/'> > >    { };

    struct Comment :
        Or<LineComment, FullComment> { };

    struct WS : 
        Star<Or<Char<' '>, Char<'\t'>, NewLine, Comment, Char<'\r'>, Char<'\v'>, Char<'\f'> > >    { };

    template<typename R>
    struct Tok : 
        Seq<R, WS> { };

    template<typename T>
    struct Keyword : 
        Tok<Seq<T, NotAlphaNum > > { };

    template<char C>
    struct CharTok :
        Seq<Char<C>, WS> { };

    struct SymName : 
        Plus<SymChar> { };

    struct AlphaName :
        Ident { };

    struct Name :
        Or<AlphaName, SymName> { };

    template<typename R, typename D>
    struct DelimitedList : 
       Or<Seq<R, Plus<Seq<D, R> > >, Opt<R> >
    { };

    template<typename First, typename T, typename Last>
    struct StoreCommaList :
        Seq<
            First, 
            Or<
                Last, 
                Seq<
                    Store<T>, 
                    Star<
                        Seq<
                            CharTok<','>, 
                            Store<T> 
                        > 
                    >,
                    Finao<Last>
                >
            > 
        >
    { };


    template<typename R>
    struct CommaList : 
       DelimitedList<R, CharTok<','> > { };

    template<typename R>
    struct Braced : 
        Seq<CharTok<'{'>, R, CharTok<'}'> > { };

    template<typename R>
    struct BracedList : 
        Seq<CharTok<'{'>, Star<R>, Finao<CharTok<'}'> > > { };

    template<typename R>
    struct StoreBracedList : 
        Seq<CharTok<'{'>, Star<Store<R> >, Finao<CharTok<'}'> > > { };

    template<typename R>
    struct BracedCommaList : 
        Braced<CommaList<R> > { };

    template<typename R>
    struct Paranthesized  : 
        Seq<CharTok<'('>, R, Finao<CharTok<')'> > > { };

    template<typename R>
    struct ParanthesizedCommaList : 
        Paranthesized<CommaList<R> > { };

    struct CharCharLiteral : 
        Or<Seq<Char<'\\'>, NotChar<'\n'> >, AnyCharExcept<CharSet<'\n', '\'' > > > { };

    struct CharLiteral : 
        Seq<Char<'\''>, CharCharLiteral, Finao<Char<'\''> > > { };

    struct StringCharLiteral : 
        Or<Seq<Char<'\\'>, NotChar<'\n'> >, AnyCharExcept<CharSet<'\n', '\"' > > > { };

    struct StringLiteral : 
        Seq<Char<'\"'>, Star<StringCharLiteral>, Finao<Char<'\"'> > > { };

    struct BinaryDigit : 
        Or<Char<'0'>, Char<'1'> > { };

    struct BinNumber : 
        Seq<CharSeq<'0', 'b'>, Plus<BinaryDigit> > { };

    struct HexNumber : 
        Seq<CharSeq<'0', 'x'>, Plus<HexDigit> > { };

    struct DecNumber : 
        Seq<Opt<Char<'-'> >, Plus<Digit>, Opt<Seq<Char<'.'>, Star<Digit> > > > { };

    struct NEW : Keyword<CharSeq<'n','e','w'> > { };
    struct DELETE : Keyword<CharSeq<'d','e','l','e','t','e'> > { };
    struct VAR : Keyword<CharSeq<'v','a','r'> > { };
    struct ELSE : Keyword<CharSeq<'e','l','s','e'> > { };
    struct IF : Keyword<CharSeq<'i','f'> > { };
    struct FOREACH : Keyword<CharSeq<'f','o','r','e','a','c','h'> > { };
    struct FOR : Keyword<CharSeq<'f','o','r'> > { };
    struct WHILE : Keyword<CharSeq<'w','h','i','l','e'> > { };
    struct IN : Keyword<CharSeq<'i','n'> > { };
    struct CASE : Keyword<CharSeq<'c','a','s','e'> > { };
    struct BREAK : Keyword<CharSeq<'b','r','e','a','k'> > { };
    struct SWITCH : Keyword<CharSeq<'s','w','i','t','c','h'> > { };
    struct RETURN : Keyword<CharSeq<'r','e','t','u','r','n'> > { };
    struct DEFAULT : Keyword<CharSeq<'d','e','f','a','u','l','t'> > { };
    struct FUNCTION : Keyword<CharSeq<'f','u','n','c','t','i','o','n'> > { };
	struct DEFINE : Keyword<CharSeq<'d','e','f','i','n','e'> > { };
	struct IMPORT : Keyword<CharSeq<'i','m','p','o','r','t'> > { };
	struct CLASS : Keyword<CharSeq<'c','l','a','s','s'> > { };
	struct INTERFACE : Keyword<CharSeq<'i','n','t','e','r','f','a','c','e'> > { };
	struct MODULE : Keyword<CharSeq<'m','o','d','u','l','e'> > { };
	struct PROGRAM : Keyword<CharSeq<'p','r','o','g','r','a','m'> > { };
	struct STATIC : Keyword<CharSeq<'s','t','a','t','i','c'> > { };

    struct Literal :
        Tok<
            Or<
                Store<BinNumber>, 
                Store<HexNumber>, 
                Store<DecNumber>, 
                Store<CharLiteral>, 
                Store<StringLiteral> 
            > 
        > { };
}

#endif
